package nl.ajonker.railroad.bl;

import nl.ajonker.railroad.dl.SwitchRail;
import nl.ajonker.railroad.sl.LogProcessor;
import nl.ajonker.railroad.sl.SwitchService;

import java.io.IOException;
import java.io.PrintWriter;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.List;

public class NetworkSwitchService implements SwitchService {
    private static final int SOCKET_TIMEOUT = 1000; // 1 second
    private LogProcessor log;
    private String hostname = "192.168.15.225";
    private Integer port = 4660;

    public NetworkSwitchService() {
        // default constructor
    }

    public NetworkSwitchService(LogProcessor log) {
        this.log = log;
    }

    @Override
    public void setLogProcessor(LogProcessor logProcessor) {
        this.log = logProcessor;
    }

    @Override
    public void setAddress(String hostname, Integer port) {
        this.hostname = hostname;
        this.port = port;
    }

    @Override
    public String getHostname() {
        return hostname;
    }

    @Override
    public Integer getPort() {
        return port;
    }

    @Override
    public void performSwitch(SwitchRail rail) throws IOException {
        if (rail.getSwitchState() == SwitchRail.SwitchState.STRAIGHT)
            performSwitch(rail, SwitchRail.SwitchState.DIVERGING);
        else
            performSwitch(rail, SwitchRail.SwitchState.STRAIGHT);
    }

    @Override
    public void performSwitch(SwitchRail rail, SwitchRail.SwitchState state) throws IOException {
        if (log != null)
            log.processLog("NetworkSwitchService performing switch to " + state + " for rail " + rail.getName());

        Socket socket = null;
        PrintWriter out = null;
//        InputStreamReader in = null;

        try {
            socket = new Socket(getAddress(), port);
            socket.setSoTimeout(SOCKET_TIMEOUT);
            out = new PrintWriter(socket.getOutputStream(), true);
//            in = new InputStreamReader(socket.getInputStream());

            String command = SwitchCommand.getCommand(rail.getSwitchAddress(), state);
            out.println(command);
            out.flush();
            if (log != null)
                log.processLog("Command " + command + " sent");
        } catch (IOException e) {
            if (log != null)
                log.processLog("Error opening socket: " + e.getMessage());
            throw e;
        } finally {
            try {
                if (out != null)
                    out.close();
//                if (in != null)
//                    in.close();
                if (socket != null)
                    socket.close();
            } catch (IOException e) {
                // do nothing
            }
        }
    }

    @Override
    public void initialize(List<SwitchRail> rails) {
        try {
            for (SwitchRail rail : rails) {
                performSwitch(rail, SwitchRail.SwitchState.STRAIGHT);
            }
        } catch (IOException e) {
            // do nothing, just stop initializing
        }
    }

    private InetAddress getAddress() throws UnknownHostException {
        return Inet4Address.getByName(hostname);
    }
}
